package com.tuzhi.util;

import org.apache.commons.collections.MapUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.*;

public class MapTzUtil extends MapUtils {

    public static BigDecimal getBigDecimal(Map map, Object key) {
        if (map != null) {
            Object obj = map.get(key);
            if (obj != null) {
                if (obj instanceof BigDecimal) {
                    return (BigDecimal) obj;
                } else {
                    try {
                        return new BigDecimal(obj + "");
                    } catch (Exception e) {
                        //
                    }
                }
            }
        }
        return null;
    }

    /**
     * 如果为空转 new HashMap<>();
     * @param map
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> null2Instance(Map<K, V> map) {
        if (map == null) {
            return new HashMap<>();
        }
        return map;
    }

    /**
     * 如果是空的都转为null
     * @param map
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> empty2Null(Map<K, V> map) {
        if (isEmpty(map)) {
            return null;
        }
        return map;
    }

    /**
     * 取两个Map中的交集，以mainMap中的为准
     * @param mainMap 主Map
     * @param minorMap  次Map
     * @return
     */
    public static Map intersection(Map mainMap, Map minorMap) {
        Map map = new HashMap();
        if (isNotEmpty(mainMap) && isNotEmpty(minorMap)) {
            for (Object obj : mainMap.keySet()) {
                if (minorMap.containsKey(obj)) {
                    map.put(obj, mainMap.get(obj));
                }
            }
        }
        return map;
    }

    /**
     * 把主Map中和次Map中相交的替换次Map中的值
     * @param mainMap
     * @param minorMap
     * @return
     */
    public static Map replaceIintersect(Map mainMap, Map minorMap) {
        if (isEmpty(minorMap)) {
            return mainMap;
        }

        Map map = new HashMap();
        if (isNotEmpty(mainMap)) {
            for (Object obj : mainMap.keySet()) {
                if (minorMap.containsKey(obj)) {
                    map.put(obj, minorMap.get(obj));
                } else {
                    map.put(obj, mainMap.get(obj));
                }
            }
        }
        return map;
    }

    /**
     * 把Map的key排序按List返回
     * key值必须是可以比较的
     * @param map
     * @param method
     * @param <K>
     * @return
     */
    public static <K extends Comparable<? super K>> List<K> getSortKeyList(Map<K, ?> map, final int method) {
        if (map == null || map.isEmpty()) {
            return null;
        }

        List<K> rs = new LinkedList<>(map.keySet());
        Collections.sort(rs, new Comparator<K>(){
            @Override
            public int compare(K key1, K key2)
            {
                return (key1.compareTo(key2)) * method;
            }
        });

        return rs;
    }

    /**
     * 把Map的value排序按List返回
     * @param map
     * @param method
     * @param <V>
     * @return
     */
    public static <V extends Comparable<? super V>> List<V> getSortValueList(Map<?, V> map, final int method) {
        if (map == null || map.isEmpty()) {
            return null;
        }

        List<V> rs = new LinkedList<>(map.values());
        Collections.sort(rs, new Comparator<V>(){
            @Override
            public int compare(V v1, V v2)
            {
                return (v1.compareTo(v2)) * method;
            }
        });

        return rs;
    }

    /**
     * Map 按照key排序
     * key值必须是可以比较的
     * @param map 需要排序的Map
     * @param method 排序方式，-1为降序， 1为升序
     * @return 排序结果LinkedHashMap
     * */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, final int method){
        if (map == null || map.isEmpty()) {
            return null;
        }

        List<Map.Entry<K, V>> linkedList = new LinkedList<>(map.entrySet());
        Collections.sort(linkedList, new Comparator<Map.Entry<K, V>>(){
            @Override
            public int compare(Map.Entry<K, V> map1, Map.Entry<K, V> map2)
            {
                return (map1.getKey().compareTo(map2.getKey())) * method;
            }
        });

        Map<K, V> result = new LinkedHashMap<>();
        for (Map.Entry<K, V> entry : linkedList) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    /**
     * Map转对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T mapToObject(Map<String, Object> map, Class<T> beanClass) throws Exception {
        if (map == null)
            return null;

        Object obj = beanClass.newInstance();

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            int mod = field.getModifiers();
            if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
                continue;
            }

            if(map.get(field.getName()) == null){
                continue;
            }

            field.setAccessible(true);
            if(field.getType().getName().equals("java.lang.Long")){
                field.set(obj, Long.valueOf(map.get(field.getName()) + ""));
            }else if(field.getType().getName().equals("java.lang.Double")){
                field.set(obj, Double.valueOf(map.get(field.getName()) + ""));
            }else if(field.getType().getName().equals("java.lang.Integer")){
                field.set(obj, Integer.valueOf(map.get(field.getName()) + ""));
            }else{
                field.set(obj, map.get(field.getName()));
            }
        }

        return (T) obj;
    }

    /**
     * 对象转Map
     * @param obj
     * @return
     * @throws Exception
     */
    public static Map<String, Object> objectToMap(Object obj) throws Exception {
        if(obj == null){
            return null;
        }

        Map<String, Object> map = new HashMap<String, Object>();

        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
//            Object tmpObj = field.get(obj);
            map.put(field.getName(), field.get(obj));
        }

        return map;
    }


    public static void main(String[] args) {

        Map map = new HashMap();
        map.put("s", "111");
        map.put("b", true);
//        map.put(33, 33);

        Map map2 = new HashMap();
        map2.put("s", "1112");
        map2.put(33, 33);

        Map map3 = new HashMap();
        map3.put("s", "1112");
        map3.put("ss", "111");


        ///////////////////////////////// 交集
        Map tmpMap = intersection(map, map2);
        System.out.println(tmpMap);

        ///////////////////////////////// 替换交集
        //把map中和map2中相交的替换为map2的value，map不相交的保留
        tmpMap = replaceIintersect(map, map2);
        System.out.println(tmpMap);

        ////////////////////////////////// map转对象
//        A a = null;
//        try {
//            a = mapToObject(map, A.class);
//            System.out.println(a);  //空属性，会保留key，value为空
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        /////////////////////////////////// 获取map中key排序后的内容，按list返回
        List list = getSortKeyList(map, 1);
        System.out.println(list);


        /////////////////////////////////// 获取map中value排序后的内容，按list返回
        List list2 = getSortValueList(map3, 1);
        System.out.println(list2);

        ////////////////////////////////////    对象转换为map
//        try {
//            Map map1 = objectToMap(a);
//            System.out.println(map1);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        ////////////////////////////////////    返转k,v
        Map tmpMap2 = invertMap(map3);
        System.out.println(tmpMap2);


        /////////////////////////////////
        System.out.println(getInteger(map2,  33));
        System.out.println(getInteger(map,  "s"));
        System.out.println(getInteger(map,  "d"));

    }

}
